import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

///
///Create by gjh on 2022/1/21
///
class HanziWidget extends StatefulWidget {
  final double size;
  final String hanzi;

  HanziWidget({this.size = 100, this.hanzi = "我"});

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return HanziState();
  }
}

class HanziState extends State<HanziWidget> {
  List<Map> hanziData = [];
  bool isAnimation = false;
  Timer interval;
  int bhIndex = 0, pointIndex = 0;
  List resultMedians = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _copyDbFileToCacheDocument();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    interval?.cancel();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return GestureDetector(
      onTap: () {
        if (isAnimation) {
          return;
        }
        resultMedians = [];
        isAnimation = true;
        interval = Timer.periodic(Duration(milliseconds: 100), (timer) {
          var medians = jsonDecode(hanziData[0]['points'])['medians'];
          List bh;
          if (resultMedians.length == 0||bhIndex>=resultMedians.length) {
            bh = [];
          } else {
            bh = resultMedians[bhIndex];

          }
          print("bhIndex:$bhIndex        pointIndex:$pointIndex ");
          bh.add(medians[bhIndex][pointIndex]);
          if(resultMedians.length==0||bhIndex>=resultMedians.length){
            resultMedians.add(bh);
          }else{
            resultMedians.removeAt(bhIndex);
            resultMedians.insert(bhIndex, bh);
          }
          print("resultMedians:$resultMedians");
          setState(() {

          });
          pointIndex++;
          if (pointIndex >= medians[bhIndex].length) {
            pointIndex = 0;
            bhIndex++;
          }
          if (bhIndex >= medians.length) {
            interval.cancel();
            isAnimation =false;
            pointIndex = 0;
            bhIndex = 0;
          }
        });
      },
      child: Container(
        width: widget.size,
        color: Colors.black,
        height: widget.size,
        child: Stack(
          alignment: Alignment.center,
          children: [
            // Image.asset("assets/bg.png"),
            CustomPaint(
              painter: HanziPaintr(
                  hanziData.length > 0
                      ? jsonDecode(hanziData[0]['points'])['strokes']
                      : null,
                  hanziData.length > 0 ? resultMedians : null),
              size: Size(widget.size, widget.size),
            )
          ],
        ),
      ),
    );
  }

  //将flutter路径下的db文件,copy到android/ios的 缓存目录下
  _copyDbFileToCacheDocument() async {
    var databasesPath = await getDatabasesPath();
    var path = join(databasesPath, 'hanzi.db');

    // delete existing if any
    await deleteDatabase(path);

    // Make sure the parent directory exists
    try {
      await Directory(dirname(path)).create(recursive: true);
    } catch (_) {}

    // Copy from asset
    // var data = await rootBundle.load(join('assets/dbfile/hanzi.db'));
    var data = await rootBundle.load(join('assets', 'hanzi.db'));

    List<int> bytes =
        data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    // Write and flush the bytes written
    await File(path).writeAsBytes(bytes, flush: true);

    //从缓存目录读取db文件里面的数据
    queryData();
  }

  //从缓存目录读取db文件里面的数据
  queryData() async {
    var databasesPath = await getDatabasesPath();
    var path = join(databasesPath, 'hanzi.db');
    // open the database
    var db = await openDatabase(path);

    // Our database as a single table with a single element
    hanziData =
        await db.rawQuery('SELECT * FROM hzdb WHERE text = ?', [widget.hanzi]);
    print('data ${jsonDecode(hanziData[0]["points"])}');
    setState(() {});

    await db.close();
  }
}

class HanziPaintr extends CustomPainter {
  Map<String, dynamic> hanziData;
  List strokes;
  List medians;
  int size = 100;
  double scale;
  Paint hzPaint = new Paint()
    ..strokeWidth = 5
    ..style = PaintingStyle.fill
    ..color = Colors.grey;

  HanziPaintr(this.strokes, this.medians) {
    this.scale = 1000 / this.size;
  }

  @override
  void paint(Canvas canvas, Size size) {
    if (strokes == null) {
      return;
    }
    print("size.widht: ${size.width}");
    this.scale = 1000 / size.width / 2;
    canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), hzPaint);
    hzPaint.strokeWidth = 1;
    canvas.drawLine(Offset.zero, Offset(size.width, 0), hzPaint);
    canvas.drawLine(Offset.zero, Offset(0, size.height), hzPaint);
    canvas.drawLine(
        Offset(size.width, 0), Offset(size.width, size.height), hzPaint);
    canvas.drawLine(
        Offset(0, size.height), Offset(size.width, size.height), hzPaint);
    hzPaint.color = Colors.redAccent;
    canvas.drawLine(Offset.zero, Offset(size.width, size.height), hzPaint);
    canvas.drawLine(Offset(0, size.height), Offset(size.width, 0), hzPaint);
    canvas.drawLine(Offset(0, size.height / 2),
        Offset(size.width, size.height / 2), hzPaint);
    canvas.drawLine(Offset(size.width / 2, 0),
        Offset(size.width / 2, size.height), hzPaint);
    // canvas.restore();
    // canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());
    print(strokes);
    // TODO: implement paint
    for (int i = 0; i < strokes.length; i++) {
      var element = strokes[i];
      print("element:" + element);
      RegExp exp = RegExp(r"(^|\s+)(?=[A-Z])");
      var lists = element.toString().split(exp);
      print("lists" + lists.toString());
      var temp = [];
      Path path = new Path();
      hzPaint.strokeWidth = 5;
      hzPaint.color = Colors.grey;
      lists.forEach((e) {
        if (e != " ") {
          temp.add(e);
          // print("---------eee:" + e);
          var parts = e.split(RegExp(r"\s+"));
          var tempParts = [];
          for (int i = 0; i < parts.length; i++) {
            if (i == 0) {
              tempParts.add(parts[i]);
            } else {
              if (i % 2 == 0) {
                //y坐标点
                // tempParts.add(double.parse(parts[i])/scale);
                tempParts.add(1000 - double.parse(parts[i]) - 100);
              } else {
                //x坐标点
                tempParts.add(double.parse(parts[i]));
                // tempParts.add(double.parse(parts[i]));
              }
            }
          }
          // print(" parts : $parts");
          if (tempParts[0] == "M") {
            path.moveTo(tempParts[1] / 10, tempParts[2] / 10);
          } else if (parts[0] == "L") {
            path.lineTo(tempParts[1] / 10, tempParts[2] / 10);
          } else if (parts[0] == "C") {
            path.cubicTo(
                tempParts[1] / 10,
                tempParts[2] / 10,
                tempParts[3] / 10,
                tempParts[4] / 10,
                tempParts[5] / 10,
                tempParts[6] / 10);
          } else if (parts[0] == "Q") {
            path.quadraticBezierTo(tempParts[1] / 10, tempParts[2] / 10,
                tempParts[3] / 10, tempParts[4] / 10);
          }
        }
      });
      print("---------" + temp.toString());
      var pathMetrics = path.computeMetrics(forceClosed: false);
      var list = pathMetrics.toList();
      var length = list.length.toInt();
      Path linePath = new Path();
      for (int i = 0; i < length; i++) {
        var extractPath =
            list[i].extractPath(0, list[i].length, startWithMoveTo: true);
        linePath.addPath(extractPath, Offset(0, 0));
      }
      canvas.drawPath(linePath, hzPaint);
    }

    animatClcik(canvas, size);

    // for (int i = 0;
    //     i < strokes.length;
    //     i++) {
    //   var element = strokes[i];
    //   print("element:" + element);
    //   RegExp exp = RegExp(r"(^|\s+)(?=[A-Z])");
    //   var lists = element.toString().split(exp);
    //   print("lists" + lists.toString());
    //   var temp = [];
    //   Path path = new Path();
    //   hzPaint.blendMode = BlendMode.srcIn;
    //   hzPaint.strokeWidth = 5;
    //   hzPaint.color = Colors.black;
    //   lists.forEach((e) {
    //     if (e != " ") {
    //       temp.add(e);
    //       print("---------eee:" + e);
    //       var parts = e.split(RegExp(r"\s+"));
    //       var tempParts = [];
    //       for (int i = 0; i < parts.length; i++) {
    //         if (i == 0) {
    //           tempParts.add(parts[i]);
    //         } else {
    //           if (i % 2 == 0) {
    //             //y坐标点
    //             // tempParts.add(double.parse(parts[i])/scale);
    //             tempParts.add(1000 - double.parse(parts[i]) - 80);
    //           } else {
    //             //x坐标点
    //             tempParts.add(double.parse(parts[i]));
    //             // tempParts.add(double.parse(parts[i]));
    //           }
    //         }
    //       }
    //       print(" parts : $parts");
    //       if (tempParts[0] == "M") {
    //         path.moveTo(tempParts[1] / 10, tempParts[2] / 10);
    //       } else if (parts[0] == "L") {
    //         path.lineTo(tempParts[1] / 10, tempParts[2] / 10);
    //       } else if (parts[0] == "C") {
    //         path.cubicTo(
    //             tempParts[1] / 10,
    //             tempParts[2] / 10,
    //             tempParts[3] / 10,
    //             tempParts[4] / 10,
    //             tempParts[5] / 10,
    //             tempParts[6] / 10);
    //       } else if (parts[0] == "Q") {
    //         path.quadraticBezierTo(tempParts[1] / 10, tempParts[2] / 10,
    //             tempParts[3] / 10, tempParts[4] / 10);
    //       }
    //     }
    //   });
    //   print("---------" + temp.toString());
    //   var pathMetrics = path.computeMetrics(forceClosed: false);
    //   var list = pathMetrics.toList();
    //   var length = list.length.toInt();
    //   Path linePath = new Path();
    //   for (int i = 0; i < length; i++) {
    //     var extractPath =
    //         list[i].extractPath(0, list[i].length, startWithMoveTo: true);
    //     linePath.addPath(extractPath, Offset(0, 0));
    //   }
    //   canvas.drawPath(linePath, hzPaint);
    // }
    // // 这里可以只显示3D效果
    canvas.restore();
  }


  animatClcik(Canvas canvas, Size size) {
    if(medians == null){
      return;
    }
    canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());


    print("animatClcik---------$medians");
    hzPaint.blendMode = BlendMode.src;
    hzPaint.strokeWidth = 1;
    hzPaint.strokeCap = StrokeCap.round;
    hzPaint.style = PaintingStyle.fill;
    hzPaint.color = Colors.white;
    for (int i = 0; i < medians.length; i++) {
      print("animatClcik --------------111111111:::$i");
      for (int j = 0; j < medians[i].length; j++) {
        print("animatClcik --------------222222222==$j");
        Path path = new Path();
        if(j==0){
          path.moveTo(medians[i][j][0]/10 , (1000 - medians[i][j][1]-100)/10);
        }else{
          path.lineTo(medians[i][j][0]/10, (1000 - medians[i][j][1]-100)/10);
          canvas.drawLine(Offset(medians[i][j-1][0]/10, (1000 - medians[i][j-1][1]-100)/10), Offset(medians[i][j][0]/10,(1000 - medians[i][j][1]-100)/10), hzPaint);
        }
      }
    }
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return true;
  }
}
